package cn.xiaoliu.hrm.config;

import cn.xiaoliu.hrm.authen.MyAuthenFailedHandler;
import cn.xiaoliu.hrm.authen.MyAuthenSuccessHandler;
import cn.xiaoliu.hrm.author.MyAuthorDeniedHandler;
import cn.xiaoliu.hrm.domain.Permission;
import cn.xiaoliu.hrm.filter.SmsCodeFilter;
import cn.xiaoliu.hrm.mapper.PermissionMapper;
import cn.xiaoliu.hrm.service.MyUserDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableWebSecurity //开启Security安全配置
@EnableGlobalMethodSecurity(prePostEnabled = true ) //开启方法注解授权
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter{
    @Autowired
    private DataSource dataSource;
    @Autowired
    private SmsAuthConfig smsAuthConfig;

    @Autowired
    private MyUserDetail myUserDetail;
    //记住我功能实现（token存储方案）
    @Bean
    public PersistentTokenRepository tokenStore(){
        JdbcTokenRepositoryImpl repository = new JdbcTokenRepositoryImpl();
        repository.setDataSource(dataSource);
        //如果数据库没有这个表就会创建一个，如果有了就会报错
        //repository.setCreateTableOnStartup(true);
        return repository;
    }


    /*@Autowired
    private PermissionMapper permissionMapper;*/

   /* @Override
    @Bean
    protected UserDetailsService userDetailsService() {
        //模拟一个用户
        User user = new User("admin", "1", new ArrayList<>());
        InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager(user);
        return userDetailsManager;
    }*/
    @Bean
    public PasswordEncoder getEncoder(){

        return new BCryptPasswordEncoder();
    }
/*    //加密
    public static void main(String[] args) {
        String pwd = "1";
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        System.out.println("  "+encoder.encode(pwd));
        System.out.println(encoder.encode(pwd));
    }*/
/*    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //查询到所有的权限
        List<Permission> permissions = permissionMapper.selectList(null);


        //配置http安全配置
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry expressionInterceptUrlRegistry = http.authorizeRequests();//所有请求都需要权限
        //将分配权限的权利交给springsecurity
        permissions.stream().forEach(permission -> {
            expressionInterceptUrlRegistry.antMatchers(permission.getResource()).hasAuthority(permission.getSn());
        });

        expressionInterceptUrlRegistry.antMatchers("/login").permitAll()  //允许登录页面放行
          .antMatchers("/login.html").permitAll() //对自定义的登录页面放行
          .anyRequest().authenticated()  //其他请求都要认证之后才能访问
          .and().formLogin()   //允许表单提交
          //.successForwardUrl("/test/success")  //认证成功之后跳转的路径
           .successHandler(new MyAuthenSuccessHandler()) //成功后的信息跳转
           .failureHandler(new MyAuthenFailedHandler())  //登录失败过后跳转
          .loginPage("/login.html") //登录页面跳转地址
          .loginProcessingUrl("/login")  //登录处理地址，这个必须写
          .and().logout().permitAll()   //登出界面允许放行
          .and().csrf().disable(); //关闭跨站
    }*/
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //配置http安全配置
        http.authorizeRequests()//所有请求都需要权限
          .antMatchers(HttpMethod.POST,"/login","/sms/send/*","/smslogin").permitAll()  //允许登录页面放行
          .antMatchers("/login.html").permitAll() //对自定义的登录页面放行
          .anyRequest().authenticated()  //其他请求都要认证之后才能访问
          .and().formLogin()   //允许表单提交
          //.successForwardUrl("/test/success")  //认证成功之后跳转的路径
           .successHandler(new MyAuthenSuccessHandler()) //成功后的信息跳转
           .failureHandler(new MyAuthenFailedHandler())  //登录失败过后跳转
          .loginPage("/login.html") //登录页面跳转地址
          .loginProcessingUrl("/login")  //登录处理地址，这个必须写
          .and().logout().permitAll()   //登出界面允许放行
          .and().csrf().disable(); //关闭跨站
        //授权异常处理
        http.exceptionHandling().accessDeniedHandler(new MyAuthorDeniedHandler());

        //记住我功能实现
        http.rememberMe()
                .tokenRepository(tokenStore())  //采用那种持久化
                .tokenValiditySeconds(3600)  //设置token过期时间
                .userDetailsService(myUserDetail); //用来加载用户信息的

        SmsCodeFilter smsCodeFilter = new SmsCodeFilter();
        //添加验证码检查的filter
        http.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class);
        //添加自己写的短信验证的配置
        http.apply(smsAuthConfig);
    }
}
